# -*- coding: utf-8 -*-
import random
from SerialWork import SerialWork
from PyQt5.QtCore import pyqtSignal, QObject, QTimer

class SerialProbe(QObject):
   dataReceived = pyqtSignal(object)
   
   CODE_ERROR, CODE_SENSOR = 0, 1
   ERR_BADHEADER, ERR_BADVALUE, ERR_BADCMD, ERR_TIMEOUT = 0, 1, 2, 3
   
   def __init__(self, _port="/dev/ttySAC3", _baudrate=19200):
      super().__init__()
      self.serialwork = SerialWork(_port, _baudrate)
      self.serialwork.setRcvCallBack(self.dataParserWithFilter)
      self.serialwork.open()

      self.jobtimer = QTimer()
      self.jobtimer.timeout.connect(self.sendCmd)
      self.jobtimer.start(50)

      self.flagReadData = False
      self.serialWdg = 15

      self.dataBuffered = []
      self.filterCounter = 5

   def ReadDataTest(self):
      if self.flagReadData == True:
         data = str(random.uniform(2,3))
         data = data[0:6]
         cmd = "data(V) "+ data
         self.serialwork.sendData(cmd.encode("utf-8"))

   def sendCmd(self):
      if self.flagReadData == False: return

      # Check if the every cmd is answered by the stm32
      if self.serialWdg == 0:
         data = {}
         data['code'] = self.CODE_ERROR
         data['value'] = self.ERR_TIMEOUT
         self.flagReadData = False
         self.dataReceived.emit(data)
      else:
         self.serialWdg = self.serialWdg - 1

      cmd="data"
      self.serialwork.sendData(cmd.encode("utf-8"))

   def sendReadCmd(self):
      cmd="data"
      self.serialwork.sendData(cmd.encode("utf-8"))

   def startReadData(self):
      self.serialWdg = 15
      self.flagReadData = True

   def stopReadData(self):
      self.flagReadData = False

   def dataParser(self, rcvData):
      self.serialWdg = 15
      end_str = b"\x0d\x0a"

      data={}
      if rcvData[0:4] == b'data' and rcvData.endswith(end_str):
         try:
            sensor_value = float(rcvData[8:14])
            data['code'] = self.CODE_SENSOR
            data['value'] = sensor_value
            self.dataReceived.emit(data)
         except:
            data['code'] = self.CODE_ERROR
            data['value'] = self.ERR_BADVALUE
            print("Bad sensor data: " + rcvData.hex(" "))
            self.sendReadCmd()
      else:
         data['code'] = self.CODE_ERROR
         data['value'] = self.ERR_BADHEADER
         print("Incomplete sensor data: " + rcvData.hex(" "))
         self.sendReadCmd()

   def readDataWithFilter(self):
      self.dataBuffered = []
      self.flagReadData = True

   def dataParserWithFilter(self, rcvData):
      self.serialWdg = 15
      sensor_value = 0.

      if rcvData[0:4] == b'data' and rcvData.endswith(b"\x0d\x0a"):
         try:
            sensor_value = float(rcvData[8:14])
            self.dataBuffered.append(sensor_value)
            print("sensor data buff: ", self.dataBuffered)
         except:
            print("Bad sensor data: " + rcvData.hex(" "))
      else:
         print("Incomplete sensor data: " + rcvData.hex(" "))

      if len(self.dataBuffered) >= self.filterCounter:
         filtered_data={}
         self.flagReadData = False
         filtered_data['code'] = 1
         filtered_data['value'] = self.filterData(self.dataBuffered)
         self.dataReceived.emit(filtered_data)

   def filterData(self, data):
      maxValue = data[0]
      minValue = data[0]
      summary = 0
      length = len(data)

      if(length < 3):
         raise Exception("Filter Error: the length of data[] max >=3")

      for num in data:
         summary = summary + num
         if num > maxValue:
            maxValue = num
         if num < minValue:
            minValue = num
      summary = summary - maxValue - minValue

      return summary/(length-2)

   def setRcvCallBack(self, function):
      self.dataReceived.connect(function)

   def openSerialPort(self):
      self.serialwork.open()

   def errorString(self, errCode):
      if errCode == 0:
         return "Bad cmd header!"
      if errCode == 1:
         return "Bad value, expect 6 bytes for float!"
      if errCode == 2:
         return "cry..."
      if errCode == 3:
         return "No response from hardware!"

   def testRcv(self, rcvData):
      print(rcvData)

if __name__ == "__main__":
   port = SerialProbe()
   port.setRcvCallBack(port.testRcv)
   port.dataParser(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34\x39\x0d\x0a')
   port.dataParser(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34')
   port.dataParser(b'\x64\x61\x74\x61\x28\x56')
   port.dataParserWithFilter(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34\x39\x0d\x0a')
   port.dataParserWithFilter(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34\x39\x0d\x0a')
   port.dataParserWithFilter(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34\x39\x0d\x0a')
   port.dataParserWithFilter(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34\x39\x0d\x0a')
   port.dataParserWithFilter(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34\x39\x0d\x0a')
   port.dataParserWithFilter(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34\x39\x0d\x0a')
   port.dataParserWithFilter(b'\x64\x61\x74\x61\x28\x56\x29\x09\x32\x2e\x39\x35\x34\x39\x0d\x0a')

